package com.atguigu.tingshu.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.AlbumClientFeign;
import com.atguigu.tingshu.album.client.TrackClientFeign;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.IdWorker;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.order.OrderDerate;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.model.user.VipServiceConfig;
import com.atguigu.tingshu.order.mapper.OrderDerateMapper;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.payment.client.AccountPayFeignClient;
import com.atguigu.tingshu.payment.client.PaymentFeignClient;
import com.atguigu.tingshu.user.client.UserClientFeign;
import com.atguigu.tingshu.vo.order.OrderDerateVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.atguigu.tingshu.vo.order.TradeVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaSigner;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.security.interfaces.RSAPrivateKey;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderDerateMapper orderDerateMapper;
    @Autowired
    private UserClientFeign userClientFeign;
    @Autowired
    private AlbumClientFeign albumClientFeign;
    @Autowired
    private TrackClientFeign trackClientFeign;
    @Autowired
    private RSAPrivateKey rsaPrivateKey;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Resource
    private PaymentFeignClient paymentFeignClient;
    @Resource
    private AccountPayFeignClient accountPayFeignClient;

    @Override
    public Object trade(TradeVo tradeVo) {
        // 包装返回结果
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        // 判断订单类型
        String itemType = tradeVo.getItemType();
        // 付款项目类型: 1001-专辑 1002-声音 1003-vip会员
        switch (itemType) {
            case "1001" -> orderInfoVo = initAlbumOrder(tradeVo.getItemId());
            case "1002" -> orderInfoVo = initTrackOrder(tradeVo.getItemId(), tradeVo.getTrackCount());
            case "1003" -> orderInfoVo = initVipOrder(tradeVo.getItemId());
        }
        // 时间戳
        orderInfoVo.setTimestamp(System.currentTimeMillis());
        // 签名
        // 使用jwt工具类生成
        Jwt encode = JwtHelper.encode(JSONObject.toJSONString(orderInfoVo), new RsaSigner(rsaPrivateKey));
        // 设置签名
        orderInfoVo.setSign(encode.getEncoded());
        // 返回结果
        return orderInfoVo;
    }


    /**
     * 提交订单(立即结算)
     *
     * @param orderInfoVo
     * @return
     */
    @Override
    public Object submitOrder(OrderInfoVo orderInfoVo) {
        // 获取签名
        String sign = orderInfoVo.getSign();
        // 非空判断
        if (StringUtils.isEmpty(sign)) {
            throw new GuiguException(201, "非法请求");
        }
        try {
            // 校验签名
            Jwt jwt = JwtHelper.decodeAndVerify(sign, new RsaVerifier(SystemConstant.PUBLIC_KEY));
            // 获取载荷
            String claims = jwt.getClaims();
            // 反序列化
            orderInfoVo = JSONObject.parseObject(claims, OrderInfoVo.class);
            // 订单确认过期时间 3min
            Long timestamp = orderInfoVo.getTimestamp();
            if (System.currentTimeMillis() - timestamp >= 300000) {
                throw new GuiguException(201, "订单过期");
            }
            // 重复校验 a. 限制类型 b. 限制具体类型
//            if (!checkOrderRepeatA(orderInfoVo)){
//                throw new GuiguException(201,"重复下单");
//            }
            // 校验方案B -- 校验内容
            if (!checkOrderRepeatB(orderInfoVo)) {
                throw new GuiguException(201, "重复下单");
            }
            // 包装orderInfo的DO, 入库
            OrderInfo orderInfo = new OrderInfo();
            // 属性转移
            BeanUtils.copyProperties(orderInfoVo, orderInfo);
            orderInfo.setUserId(AuthContextHolder.getUserId());
            // 获取订单类型
            String itemType = orderInfoVo.getItemType();
            switch (itemType) {
                case "1001" -> orderInfo.setOrderTitle("专辑订单");
                case "1002" -> orderInfo.setOrderTitle("声音订单");
                case "1003" -> orderInfo.setOrderTitle("会员订单");
            }
            orderInfo.setOrderNo(orderInfoVo.getTradeNo());
            orderInfo.setOrderStatus("0901");
            // 如果保存成功
            if (save(orderInfo)) {
                // 获取订单id
                Long orderId = orderInfo.getId();
                // 包装orderDetail的DO, 入库
                List<OrderDetailVo> orderDetailVoList = orderInfoVo.getOrderDetailVoList();
                saveOrderDetail(orderDetailVoList, orderId);
                // 包装orderDerate的DO, 入库
                List<OrderDerateVo> orderDerateVoList = orderInfoVo.getOrderDerateVoList();
                saveOrderDerate(orderDerateVoList, orderId);
                // 返回结果初始化
                JSONObject result = new JSONObject();
                result.put("orderNo", orderInfo.getOrderNo());
                // 延时消息队列 -- 订单超时取消
                rabbitTemplate.convertAndSend(
                        "order_delay_exchange",
                        "order.delay.dead",
                        orderInfo.getOrderNo() + ":" + orderInfo.getUserId(),
                        message -> {
                            MessageProperties messageProperties = message.getMessageProperties();
                            // 设置消息过期时间
                            messageProperties.setExpiration(300000 + "");
                            return message;
                        });
                return result;
            }
        } catch (Exception e) {
            // 出现异常：立即放锁
            releaseLock(orderInfoVo.getOrderDetailVoList().get(0).getItemId(),
                    orderInfoVo.getItemType(),
                    AuthContextHolder.getUserId());
            throw e;
        }
        return null;
    }

    /**
     * 超时取消 / 主动取消订单
     *
     * @param orderNo
     */
    @Override
    @SneakyThrows
    public void cancelOrder(String orderNo) {
        // 设置取消状态 -- 默认主动取消
        String orderStatus = "0903";
        // 判断主动取消还是超时取消 -- 本地线程有无userId
        Long userId = AuthContextHolder.getUserId();
        if (userId == null) {
            // 超时取消 内部调用 线程无userId
            orderStatus = "0904";
            // 分割获取 orderNo & userId
            String[] split = orderNo.split(":");
            orderNo = split[0];
            userId = Long.valueOf(split[1]);
        }
        // 抢锁 userId + orderId
        RLock lock = redissonClient.getLock("OrderCancelAndPay_" + userId + "_OrderNo_" + orderNo);
        if (lock.tryLock()) {
            try {
                // 取消订单 ---> 当前用户 + 当前订单号 +未支付订单
                OrderInfo orderInfo = getOne(new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getUserId, userId)
                        .eq(OrderInfo::getOrderNo, orderNo)
                        .eq(OrderInfo::getOrderStatus, "0901"));
                // 若订单不存在 结束
                if (orderInfo == null) {
                    return;
                }
                // 修改订单状态
                orderInfo.setOrderStatus(orderStatus);
                // 更新订单信息 -- 若失败 抛异常
                if (!updateById(orderInfo)) {
                    throw new GuiguException(201, "取消失败");
                }
                // 查询订单itemId
                Long itemId = orderDetailMapper.selectItemIdByOrderId(orderInfo.getId());
                // 清理redis -- 避免影响后续下单
                releaseLock(itemId, orderInfo.getItemType(), userId);
            } catch (Exception e) {
                throw e;
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 修改订单支付状态
     *
     * @param resultString
     */
    @Override
    @SneakyThrows
    public void updateOrder(String resultString) {
        // 反序列化
        Map<String, String> result = JSONObject.parseObject(resultString, Map.class);
        // 获取订单号
        String orderNo = result.get("out_trade_no");
        // 查询订单信息：orderNo
        OrderInfo orderInfo = getOne(
                new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getOrderNo, orderNo));
        // 抢锁 userId + orderId : 取消订单与更新支付订单支付状态冲突
        RLock lock = redissonClient.getLock("OrderCancelAndPay_" + orderInfo.getUserId() + "_OrderNo_" + orderNo);
        // 加锁
        lock.lock();
        try {
            // 获取订单状态
            if (!orderInfo.getOrderStatus().equals("0902")) {
                // 若为支付 则更新
                orderInfo.setOrderStatus("0902");
                updateById(orderInfo);
                // 后续处理
                afterPaid(orderNo);
            }

        } catch (Exception e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }


    @Override
    public OrderInfo getOrderInfo(String orderNo) {
        // 构建查询条件
        LambdaQueryWrapper<OrderInfo> wrapper =
                new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getOrderNo, orderNo);
        // 设置userId
        if (AuthContextHolder.getUserId() != null) {
            wrapper.eq(OrderInfo::getUserId, AuthContextHolder.getUserId());
        }
        // 查询订单 --> orderNo & userId
        OrderInfo orderInfo = getOne(wrapper);
        // orderDetail
        List<OrderDetail> orderDetailList =
                orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>()
                        .eq(OrderDetail::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDetailList(orderDetailList);
        // orderDerate
        List<OrderDerate> orderDerateList =
                orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>()
                        .eq(OrderDerate::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDerateList(orderDerateList);
        return orderInfo;
    }

    /**
     * 分页查询用户订单列表
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public Object findUserPage(Integer page, Integer size) {
        return orderInfoMapper.selectUserOrderPage(
                new Page<OrderInfo>(page, size),
                AuthContextHolder.getUserId()
        );
    }

    /**
     * 根据用户选择的支付渠道 获取对应的支付信息
     *
     * @param orderNo
     * @param payWay
     * @return
     */
    @Override
    public Object getOrderPayInfo(String orderNo, String payWay) {
        // 校验参数
        if (StringUtils.isEmpty(orderNo) || StringUtils.isEmpty(payWay)) {
            throw new GuiguException(201, "参数错误");
        }
        // 获取UserId
        Long userId = AuthContextHolder.getUserId();
        // redis获取支付信息
        String codeUrl = (String) redisTemplate.opsForValue()
                .get("Order_PayInfo_Lock_User_" + userId + "_OrderNo_" + orderNo + "_PayWay_" + payWay);
        if (StringUtils.isNotEmpty(codeUrl)) {
            // 有 -- 直接返回  没有 -- 往下执行支付申请
            return codeUrl;
        }
        // 解决重复申请：时常限制-5min 不论支付渠道 同一用户同一订单5分钟能只能申请一次支付
        RLock lock = redissonClient
                .getLock("Order_PayInfo_Lock_User_" + userId + "_OrderNo_" + orderNo);
        if (lock.tryLock()) {
            try {
                // 查询订单信息
                OrderInfo orderInfo = getOne(new LambdaQueryWrapper<OrderInfo>()
                        .eq(OrderInfo::getUserId, userId) // 用户
                        .eq(OrderInfo::getOrderNo, orderNo) // orderNo
                        .eq(OrderInfo::getOrderStatus, "0901")); // 未付款
                // 订单是否存在
                if (orderInfo == null) {
                    throw new GuiguException(201, "订单不存在");
                }
                // 申请参数初始化
                Map<String, String> params = new HashMap<>();
                params.put("description", orderInfo.getOrderTitle());
                params.put("orderNo", orderNo);
                params.put("price", orderInfo.getOrderAmount().toString());
                // paymentType 支付类型：1301-订单 1302-充值 1303-商城
                params.put("paymentType", "1301"); // 前端没做 写死 实际由请求发送
                // 消息队列
                params.put("exchange", "payment_info_exchange");
                params.put("routingKey", "payment.order"); // 包装到attach 后续支付完成后payment_info更新订单/支付状态
                params.put("userId", userId + "");
                // 根据用户参数选择渠道
                switch (payWay) {
                    // 支付方式：1101-微信 1102-支付宝 1103-账户余额
                    case "1101" -> codeUrl = paymentFeignClient.getPayInfoFromWx(params);
                    case "1102" -> codeUrl = "Alipay"; // 不做
                    case "1103" -> codeUrl = accountPayFeignClient.getPayInfoFromAccount(params);
                }
                if (codeUrl != null) {
                    // redis储存 -- 预防多次支付请求
                    redisTemplate.opsForValue()
                            .set("Order_PayInfo_Lock_User_" + userId + "_OrderNo_" + orderNo + "_PayWay_" + payWay,
                                    codeUrl,
                                    5,
                                    TimeUnit.MINUTES);
                }
            } catch (Exception e) {
                throw e;
            } finally {
                lock.unlock();
            }
        }
        // 返回
        return codeUrl;
    }


    /**
     * 放锁
     *
     * @param itemId
     * @param itemType
     * @param userId
     */
    private void releaseLock(Long itemId, String itemType, Long userId) {
        // 获取albumId -- 声音订单
        if (itemType.equals("1002")) {
            itemId = trackClientFeign.getTrackInfoDetail(itemId).getAlbumId();
        }
        // 自动放锁：过期
        redisTemplate.expire(
                "submitOrder_" + userId + "_" + itemType + "_" + itemId,
                5,
                TimeUnit.MINUTES);
        // 手动放锁：
        redisTemplate.delete("submitOrder_" + userId + "_" + itemType + "_" + itemId);
    }


    /**
     * 校验方案A：限制类型 - 同一用户只能有一个同内容的订单
     *
     * @param orderInfoVo
     */
    private Boolean checkOrderRepeatA(OrderInfoVo orderInfoVo) {
        // 获取用户
        Long userId = AuthContextHolder.getUserId();
        // 获取内容 会员 专辑 声音(list)
        String itemType = orderInfoVo.getItemType();
        // 加分布式锁
        if (redisTemplate.opsForValue().setIfAbsent(
                "submitOrder_" + userId + "_" + itemType,
                0,
                5, TimeUnit.MINUTES)) {
            return true;
        }
        // 加锁成功，下单
        return false;
    }


    /**
     * 校验方案B：限制类型 - 同一用户只能有一个同类型的订单
     * 1. 会员：userId + itemId
     * 2. 专辑：userId + itemId
     * 3. 声音：userId +
     *
     * @param orderInfoVo
     */
    @SneakyThrows
    private Boolean checkOrderRepeatB(OrderInfoVo orderInfoVo) {
        // 获取用户
        Long userId = AuthContextHolder.getUserId();
        // 获取itemId
        Long itemId = orderInfoVo.getOrderDetailVoList().get(0).getItemId();
        // 获取订单详情 1001-专辑 1002-声音 1003-vip会员
        String itemType = orderInfoVo.getItemType();
        if (itemType.equals("1002")) {
            // itemId=trackId
            Long albumId = trackClientFeign.getTrackInfoDetail(itemId).getAlbumId();
            // 锁专辑 itemId=albumId
            if (redisTemplate.opsForValue().setIfAbsent(
                    "submitOrder_" + userId + "_" + itemType + "_" + albumId,
                    0,
                    5, TimeUnit.MINUTES)) {
                return true;
            }
        }
        // 会员 & 专辑 加锁
        if (redisTemplate.opsForValue().setIfAbsent(
                "submitOrder_" + userId + "_" + itemType + "_" + itemId,
                0,
                3, TimeUnit.MINUTES)) {
            return true;
        }
        return false;
    }


    /**
     * 保存订单折扣详情
     *
     * @param orderDerateVoList
     */
    private void saveOrderDerate(List<OrderDerateVo> orderDerateVoList, Long orderId) {
        // 非空判断 - 声音没有折扣
        if (orderDerateVoList == null) {
            return;
        }
        // 遍历保存
        orderDerateVoList.stream().forEach(orderDerateVo -> {
            // 初始化
            OrderDerate orderDerate = new OrderDerate();
            // 赋值
            BeanUtils.copyProperties(orderDerateVo, orderDerate);
            // 补全属性
            orderDerate.setOrderId(orderId);
            int insert = orderDerateMapper.insert(orderDerate);
            // 判断是否保存成功
            if (insert <= 0) {
                throw new GuiguException(201, "订单折扣详情保存失败");
            }
        });
    }

    /**
     * 保存订单详情
     *
     * @param orderDetailVoList
     */
    private void saveOrderDetail(List<OrderDetailVo> orderDetailVoList, Long orderId) {
        orderDetailVoList.stream().forEach(orderDetailVo -> {
            // 初始化
            OrderDetail orderDetail = new OrderDetail();
            // 赋值
            BeanUtils.copyProperties(orderDetailVo, orderDetail);
            // 补全orderId
            orderDetail.setOrderId(orderId);
            // 入库
            int insert = orderDetailMapper.insert(orderDetail);
            // 判断DB入库是否成功
            if (insert <= 0) {
                throw new GuiguException(201, "订单详情保存失败");
            }
        });
    }


    /**
     * 创建购买专辑订单
     *
     * @param itemId
     * @return
     */
    private OrderInfoVo initAlbumOrder(Long itemId) {
        // 获取购买详情
        AlbumInfo albumInfo = albumClientFeign.getAlbumInfo(itemId);
        // 验证albumInfo是否有值
        if (albumInfo != null && albumInfo.getId() != null) {
            // 验证albumInfo是否为付费专辑payType-0103 且为整张购买priceType-0202
            String payType = albumInfo.getPayType();
            String priceType = albumInfo.getPriceType();
            if (payType.equals("0103") && priceType.equals("0202")) {
                // 验证用户是否已经购买过
                if (orderInfoMapper.selectAlbumUnpaidOrderCount(AuthContextHolder.getUserId(), itemId) == 0) {
                    // 初始化返回对象
                    OrderInfoVo orderInfoVo = new OrderInfoVo();
                    // 查询用户Vip状态 -- 折扣分支
                    Integer vip = AuthContextHolder.getVip();
                    // 初始化折扣对象
                    BigDecimal discount = null;
                    if (vip.equals(1)) {
                        // vip会员折扣
                        discount = albumInfo.getVipDiscount();
                    } else {
                        // 普通会员折扣
                        discount = albumInfo.getDiscount();
                    }
                    // 不打折的情况
                    discount = discount.compareTo(new BigDecimal(-1)) == 0 ? new BigDecimal(1) : discount.divide(new BigDecimal(10));
                    // 返回结果-订单明显
                    OrderDetailVo orderDetailVo = new OrderDetailVo();
                    orderDetailVo.setItemId(itemId);
                    orderDetailVo.setItemName("购买专辑：" + albumInfo.getAlbumTitle());
                    orderDetailVo.setItemUrl(albumInfo.getCoverUrl());
                    orderDetailVo.setItemPrice(orderInfoVo.getOrderAmount());
                    // 初始化orderDetailVoList
                    List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
                    orderDetailVoList.add(orderDetailVo);
                    // 返回结果-减免详情
                    OrderDerateVo orderDerateVo = new OrderDerateVo();
                    // 订单减免类型 1405-专辑折扣 1406-VIP服务折
                    orderDerateVo.setDerateType("1405");
                    orderDerateVo.setDerateAmount(orderInfoVo.getDerateAmount());
                    orderDerateVo.setRemarks("专辑折扣备注");
                    // 初始化OrderDerateVoList
                    List<OrderDerateVo> OrderDerateVoList = new ArrayList<>();
                    OrderDerateVoList.add(orderDerateVo);
                    // 属性赋值
                    orderInfoVo.setTradeNo("albumOrderNo" + idWorker.nextId());
                    orderInfoVo.setItemType("1001");
                    orderInfoVo.setOriginalAmount(albumInfo.getPrice());
                    orderInfoVo.setDerateAmount(albumInfo.getPrice().multiply(new BigDecimal(1).subtract(discount)));
                    orderInfoVo.setOrderAmount(albumInfo.getPrice().multiply(discount));
                    orderInfoVo.setOrderDetailVoList(orderDetailVoList);
                    orderInfoVo.setOrderDerateVoList(OrderDerateVoList);
                    // 返回结果
                    return orderInfoVo;
                }
            }
        }
        throw new GuiguException(201, "专辑不能直接购买");
    }


    /**
     * 创建购买声音订单
     *
     * @param itemId
     * @return
     */
    private OrderInfoVo initTrackOrder(Long itemId, Integer trackCount) {
        // 订单vo初始化
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        // 查询可购买的声音信息
        JSONObject result = trackClientFeign.getTrackListAndPrice(itemId);
        // 获取单价
        BigDecimal price = new BigDecimal(result.get("price").toString());
        // 获取下单的声音列表
        List<Object> list = (List) result.get("trackInfoList");
        // 过滤条件：1 已购买
        Map<String, Object> userPaidTrackMap = userClientFeign
                .getUserPaidTrack(
                        Long.valueOf(result.get("albumId").toString()),
                        AuthContextHolder.getUserId());
        // 过滤条件：2 已下单未支付
        Map<String, Object> userTrackOrderInfoMap =
                getUserTrackOrderInfo(AuthContextHolder.getUserId());
        // 包装orderDetailVoList
        List<OrderDetailVo> orderDetailVoList = list.stream().map(o -> {
            String s = JSONObject.toJSONString(o);
            return JSONObject.parseObject(s, TrackInfo.class);
        }).filter(f -> userPaidTrackMap.get(f.getId().toString()) == null &&
                userTrackOrderInfoMap.get(f.getId().toString()) == null).limit(trackCount).map(trackInfo -> {
            // 订单详情初始化
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            orderDetailVo.setItemId(trackInfo.getId());
            orderDetailVo.setItemPrice(price);
            orderDetailVo.setItemUrl(trackInfo.getCoverUrl());
            orderDetailVo.setItemName(trackInfo.getTrackTitle());
            return orderDetailVo;
        }).collect(Collectors.toList());
        // 包装返回结果
        orderInfoVo.setTradeNo("trackOrderNo" + idWorker.nextId());
        orderInfoVo.setItemType("1002");
        orderInfoVo.setOriginalAmount(price.multiply(new BigDecimal(trackCount)));
        // 声音无折扣
        orderInfoVo.setDerateAmount(new BigDecimal(0));
        orderInfoVo.setOrderAmount(price.multiply(new BigDecimal(trackCount)));
        orderInfoVo.setOrderDetailVoList(orderDetailVoList);
        // 声音无折扣
        orderInfoVo.setOrderDerateVoList(null);
        // 返回结果
        return orderInfoVo;
    }


    /**
     * 创建购买vip订单
     *
     * @param itemId
     * @return
     */
    private OrderInfoVo initVipOrder(Long itemId) {
        // 获取购买详情
        VipServiceConfig vipServiceConfig =
                userClientFeign.getVipServiceConfig(itemId);
        // 初始化返回对象
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        // 返回结果-订单明显
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        orderDetailVo.setItemId(itemId);
        orderDetailVo.setItemName("购买VIP套餐：" + vipServiceConfig.getName());
        orderDetailVo.setItemUrl(vipServiceConfig.getImageUrl());
        orderDetailVo.setItemPrice(vipServiceConfig.getPrice());
        // 初始化orderDetailVoList
        List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
        orderDetailVoList.add(orderDetailVo);
        // 返回结果-减免详情
        OrderDerateVo orderDerateVo = new OrderDerateVo();
        // 订单减免类型 1405-专辑折扣 1406-VIP服务折
        orderDerateVo.setDerateType("1406");
        orderDerateVo.setDerateAmount(orderInfoVo.getDerateAmount());
        orderDerateVo.setRemarks("Vip折扣备注");
        // 初始化OrderDerateVoList
        List<OrderDerateVo> OrderDerateVoList = new ArrayList<>();
        OrderDerateVoList.add(orderDerateVo);
        // 属性赋值
        orderInfoVo.setTradeNo("VipOrderNo" + idWorker.nextId());
        orderInfoVo.setItemType("1003");
        orderInfoVo.setOriginalAmount(vipServiceConfig.getPrice());
        orderInfoVo.setDerateAmount(vipServiceConfig.getPrice().subtract(vipServiceConfig.getDiscountPrice()));
        orderInfoVo.setOrderAmount(vipServiceConfig.getDiscountPrice());
        orderInfoVo.setOrderDetailVoList(orderDetailVoList);
        orderInfoVo.setOrderDerateVoList(OrderDerateVoList);
        // 返回结果
        return orderInfoVo;
    }

    /**
     * 查询用户下单但未付款的声音id列表
     *
     * @param userId
     * @return
     */
    @Override
    public Map<String, Object> getUserTrackOrderInfo(Long userId) {
        // 查询用户下单但未付款的声音id列表
        List<Long> trackIdList = orderInfoMapper.selectTrackIdList(userId);
        // 转为Map后返回
        return trackIdList.stream().collect(Collectors.toMap(
                key -> key.toString(),
                value -> 0
        ));
    }


    /**
     * 订单支付后的后续处理 -- 由消息通知
     *
     * @param orderNo
     */
    private void afterPaid(String orderNo) {
        rabbitTemplate.convertAndSend("order_after_paid_fanout_exchange", "", orderNo);
    }

}
